////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "ObjectHandlerFactory.hpp"
#include "ObjectHandlers.h"

////////////////////////////////////////////////////////////
/// Constructor
////////////////////////////////////////////////////////////
ObjectHandlerFactory::ObjectHandlerFactory()
{
}

////////////////////////////////////////////////////////////
/// Destructor
////////////////////////////////////////////////////////////
ObjectHandlerFactory::~ObjectHandlerFactory()
{
    for (td_mapObjectHandler::iterator it = m_ObjectHandlers.begin();
        it != m_ObjectHandlers.end();
        ++it) {
            delete it->second.m_pHandler;
    }
    m_ObjectHandlers.clear();
}

////////////////////////////////////////////////////////////
/// Initialize the factory
////////////////////////////////////////////////////////////
bool ObjectHandlerFactory::Init() {
    // Light
    AddObjectHandler(LightHandler().GetName(), LightHandler());
    AddObjectHandler(CircleHullHandler().GetName(), CircleHullHandler());
    AddObjectHandler(ConvexHullHandler().GetName(), ConvexHullHandler());
    AddObjectHandler(TextureHullHandler().GetName(), TextureHullHandler());

    // Entity
    AddObjectHandler(BaseEntityHandler().GetName(), BaseEntityHandler());
    AddObjectHandler(ShadowCasterEntityHandler().GetName(), ShadowCasterEntityHandler());

    // AI
    AddObjectHandler(TestSteeringAIHandler().GetName(), TestSteeringAIHandler());

    return true;
}
   
////////////////////////////////////////////////////////////
/// Add an object handler
//////////////////////////////////////////////////////////// 
void ObjectHandlerFactory::AddObjectHandler(const std::string& _ObjectHandlerName, const BaseObjectHandler& _ObjectHandler, bool _bForce) {
    td_mapObjectHandler::iterator it = m_ObjectHandlers.find(_ObjectHandlerName);

    if (it != m_ObjectHandlers.end()) {
        if (_bForce) {
            delete it->second.m_pHandler;
            m_ObjectHandlers.erase( it );
            m_ObjectHandlers.insert( td_mapObjectHandler::value_type( _ObjectHandlerName, static_cast<BaseObjectHandler*>(_ObjectHandler.Clone()) ) );
        }
    } else {
        m_ObjectHandlers.insert( td_mapObjectHandler::value_type( _ObjectHandlerName, static_cast<BaseObjectHandler*>(_ObjectHandler.Clone()) ) );
    }
}

////////////////////////////////////////////////////////////
/// Get an object handler
////////////////////////////////////////////////////////////
BaseObjectHandler* ObjectHandlerFactory::GetObjectHandler(const std::string& _ObjectHandlerName) {
    td_mapObjectHandler::iterator it = m_ObjectHandlers.find(_ObjectHandlerName);

    if (it != m_ObjectHandlers.end()) {
        return it->second.m_pHandler;
    }

    return NULL;
}

////////////////////////////////////////////////////////////
/// Create an object handler
////////////////////////////////////////////////////////////
BaseObjectHandler* ObjectHandlerFactory::CreateObjectHandler(const std::string& _ObjectHandlerName) {
    td_mapObjectHandler::iterator it = m_ObjectHandlers.find(_ObjectHandlerName);

    if (it != m_ObjectHandlers.end()) {
        BaseObjectHandler* cloned = static_cast<BaseObjectHandler*>(it->second.m_pHandler->Clone());
        cloned->SetId( cloned->GetName() + wxT("_") + wxString::Format("%d", it->second.m_iNumCreated) );
        ++it->second.m_iNumCreated;
        
        return cloned;
    }

    return NULL;
}
